<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>IndexedDB easy sample.</title>
<script src="../js/jquery-1.4.4.min.js"></script>
</head>
<body>
<h1>IndexedDB easy sample.</h1>
SEARCH --&gt; <input type="text" id=search required><br/>
CREATE --&gt; name:<input type="text" id=name required>
<div id=datas></div>
<div id=mesg></div>

<script>

$('#name').change(function(){idbtest_.set({name:$(this).val(),update:new Date().toString()});});
$('#search').change(function(){idbtest_.showByIdx($(this).val());});

var idbtest_ = (function(){
	var _indexedDB = window.indexedDB || window.webkitIndexedDB || window.moz_indexedDB,
    _IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction,
    _IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange,
    _db = null,
    _ready = false;
	
	
	if(_indexedDB === 'undefined') {
		$('#mesg').html('お使いのブラウザは、indexedDBが利用できません');
	} else {
	
		var request = _indexedDB.open("testdb", "testデータベース");
		request.onsuccess = function(ev){
			$('#mesg').html("open indexedDB succeed.<br>");
			db = ev.result;
			if (db.version != "1.0") {
				var versionRequest = db.setVersion("1.0");
        $('#mesg').append("Current Version is not 1.0.<br>");
        versionRequest.ontimeout = function(event) {
          throw new Error("timeout trying to set version to 1.0");
        }

        versionRequest.onsuccess = function(event){
          if(db.objectStoreNames.contains('books')) {
            $('#mesg').append("objectStore 'books' already exist.<br>");
            start_();
          } else {
            // below line is useful for clean-up objectStore while developing. ;-)
            //db.deleteObjectStore ? db.deleteObjectStore('books') : db.removeObjectStore('books');

            // Note(2010.01.05)::
            // Indication key name does not effect in Chromium environment.
            //
            // Spec says that objectStore supports 'key generator', but I couldn't find details about it ;-(

            var store = db.createObjectStore("books", null, true);

            store.createIndex("BookName", "name", false);
            $('#mesg').append("create objectStore 'books'.<br>");
            start_();
          }
        }
			} else {
        $('#mesg').append("Current Version is 1.0.<br>");
				start_();
			}
		}
	}

  /**
   * error handling
   *
   */
  var error_ = function(ev) {
    $('#mesg').append("<span class=error>Error: "+ev.message+" ("+ev.code+")<br>");
  }

  /**
   * process start
   *
   */
  var start_ = function(){
    $('#mesg').append("start services...<br>");
    _ready = true;
    show_();
  }

  /**
   * Method to create new row
   *
   */
  var set_ = function(val){
    if(!_ready) {
      $('#mesg').append('not ready');
      return;
    }
    var objectstore = db.transaction([], _IDBTransaction.READ_WRITE)
      .objectStore('books');
    var req = objectstore.add(val, new Date().getTime());

    console.log('set');

    req.onsuccess = function(){show_()};
    req.onerror = error_;
  }

  /**
   * Method to search all values or indicated key value.
   *
   */
  var show_ = function(id){
    if(!_ready) {
      $('#mesg').append('not ready');
      return;
    }
    var html = [];

    var store =  db.transaction([], _IDBTransaction.READ_ONLY).objectStore('books');

    var req = typeof(id) === 'number'  ?  store.get(id) : store.openCursor();

    req.onsuccess = function(ev){
      if(typeof(id)==="number") {
        $('#datas').html(['<ul><li>[',id,'] => ', JSON.stringify(ev.result),'</li></ul>'].join(''));
        return;
      }

        
      var cursor = ev.result;
      if(!cursor) {
        $('#datas').html('<ul>'+html.join('')+'</ul>');
        return;
      } else {
        html.push('<li>[', cursor.key, '] => ', JSON.stringify(cursor.value),'</li>');
        cursor.continue();
      }
    }
    req.onerror = error_;
  }

  /** 
   * Medhod to search with index value.
   * 
   * If index is not restricted unique value, index.get() returns only one value.
   * So, above condition, we have to use index.openCursor() or index.openKeyCursor().
   * Those methods require IDBKeyRange Object. If you want to match only one value
   * only() method is adiquate. If you want to do range search, you bound() method'll
   * be reasonable:)
   *
   * I have to note that current chromium(10.0.626.0 (70323)) does not process openCursor()
   * etc. properly. Returns all values stored in storeObject ;-(
   * 
   */

  var showByIdx_ = function(val) {
    var store =  db.transaction([], _IDBTransaction.READ_ONLY).objectStore('books');
    var index = store.index('BookName');

    var range = new _IDBKeyRange.only(val);
    console.log(range);
    var req = index.openCursor(range);

    var html = [];

    req.onsuccess = function(ev){
      var cursor = ev.result;
      console.log(cursor);

      if(!cursor) {
        $('#datas').html('<ul>'+html.join('')+'</ul>');
        return;
      } else {
        if(typeof(cursor.value) !== 'object') {
          var _req = store.get(cursor.value);
          _req.onsuccess = function(_ev) {
            html.push('<li>[', val, '] => ', JSON.stringify(_ev.result),'</li>');
            cursor.continue();
          }
          _req.onerror = error_;
        } else {
          html.push('<li>[', cursor.key, '] => ', JSON.stringify(cursor.value),'</li>');
          cursor.continue();
        }
      }
    }
    _req.onerror = error_;
  }
    

  return {
    show: show_,
    set: set_,
    showByIdx: showByIdx_
  }
})();
</script>
</body>
</html>
